package com.rskj.cashbook.service.iml;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rskj.cashbook.dao.SqlTxtMonitorLogDao;
import com.rskj.cashbook.service.ISqlMonitorLogService;
import com.rskj.cashbook.util.SnowflakeIdWorker;
import com.rskj.cashbook.vo.SqlTxtMonitorLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.net.InetAddress;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;

@Service
@Slf4j
public class SqlMonitorLogService implements ISqlMonitorLogService {

    @Resource
    private SqlTxtMonitorLogDao sqlTxtMonitorLogMapper;

    @Resource
    private ObjectMapper objectMapper;

    // 配置参数
    @Value("${sql.monitor.enabled:true}")
    private boolean sqlMonitorEnabled;

    @Value("${sql.monitor.slow-query-threshold:1000}")
    private Long slowQueryThreshold;

    @Value("${sql.monitor.batch-size:100}")
    private Integer batchSize;

    @Value("${sql.monitor.retention-days:30}")
    private Integer retentionDays;

    // 批量处理队列
    private final LinkedBlockingQueue<SqlTxtMonitorLog> batchQueue = new LinkedBlockingQueue<>(1000);

    @Override
    public void saveSqlLog(SqlTxtMonitorLog logger) {
        if (!sqlMonitorEnabled) {
            return;
        }

        try {
            // 设置默认值
            setDefaultValues(logger);

            // 检查是否为慢查询
            if (logger.getExecutionDuration() != null && logger.getExecutionDuration() > slowQueryThreshold) {
                log.info("检测到慢查询: {}ms, SQL: {}", logger.getExecutionDuration(), logger.getSqlText());
            }

            sqlTxtMonitorLogMapper.insert(logger);

            log.debug("SQL监控日志保存成功: {}", logger.getId());
        } catch (Exception e) {
            log.error("保存SQL监控日志失败: {}", e.getMessage(), e);
            // 不抛出异常，避免影响主业务流程
        }
    }

    @Override
    public void saveSqlLogBatch(List<SqlTxtMonitorLog> logs) {
        if (!sqlMonitorEnabled || logs == null || logs.isEmpty()) {
            return;
        }

        try {
            // 设置默认值
            logs.forEach(this::setDefaultValues);

            sqlTxtMonitorLogMapper.insertBatch(logs);

            log.info("批量保存SQL监控日志成功，数量: {}", logs.size());
        } catch (Exception e) {
            log.error("批量保存SQL监控日志失败: {}", e.getMessage(), e);
        }
    }

    @Override
    public List<SqlTxtMonitorLog> querySqlLogs(SqlTxtMonitorLog condition) {
        try {
            return sqlTxtMonitorLogMapper.selectByCondition(condition);
        } catch (Exception e) {
            log.error("查询SQL监控日志失败: {}", e.getMessage(), e);
            return List.of();
        }
    }

    @Override
    public List<SqlTxtMonitorLog> getSlowQueries(Long threshold) {
        try {
            return sqlTxtMonitorLogMapper.selectSlowQueries(threshold != null ? threshold : slowQueryThreshold);
        } catch (Exception e) {
            log.error("查询慢查询SQL失败: {}", e.getMessage(), e);
            return List.of();
        }
    }

    @Override
    public List<SqlTxtMonitorLog> getErrorQueries() {
        try {
            return sqlTxtMonitorLogMapper.selectErrorQueries();
        } catch (Exception e) {
            log.error("查询错误SQL失败: {}", e.getMessage(), e);
            return List.of();
        }
    }

    @Override
    public int cleanExpiredLogs(LocalDateTime expireTime) {
        try {
            LocalDateTime cleanTime = expireTime != null ? expireTime :
                    LocalDateTime.now().minusDays(retentionDays);
            int deletedCount = sqlTxtMonitorLogMapper.deleteExpiredLogs(cleanTime);
            log.info("清理过期SQL监控日志成功，删除数量: {}", deletedCount);
            return deletedCount;
        } catch (Exception e) {
            log.error("清理过期SQL监控日志失败: {}", e.getMessage(), e);
            return 0;
        }
    }

    @Override
    public Map<String, Object> getSqlStatistics(LocalDateTime startTime) {
        try {
            LocalDateTime statTime = startTime != null ? startTime :
                    LocalDateTime.now().minusDays(1);
            return sqlTxtMonitorLogMapper.getStatistics(statTime);
        } catch (Exception e) {
            log.error("获取SQL统计信息失败: {}", e.getMessage(), e);
            return Map.of();
        }
    }

    @Override
    @Async("sqlMonitorExecutor")
    public void saveSqlLogAsync(SqlTxtMonitorLog sqlTxtMonitorLog) {
        try {
            saveSqlLog(sqlTxtMonitorLog);
        } catch (Exception e) {
            log.error("异步保存SQL日志失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 设置默认值
     */
    private void setDefaultValues(SqlTxtMonitorLog logger) {
        if (logger.getId() == null) {
            logger.setId(SnowflakeIdWorker.getId());
        }

        if (logger.getExecutionTime() == null) {
            logger.setExecutionTime(LocalDateTime.now());
        }

        if (logger.getStatus() == null) {
            logger.setStatus("SUCCESS");
        }

        if (logger.getApplicationName() == null) {
            logger.setApplicationName("cashbook");
        }

        if (logger.getCreateDate() == null) {
            logger.setCreateDate(new java.util.Date());
        }

        if (logger.getUpdateDate() == null) {
            logger.setUpdateDate(new java.util.Date());
        }

        // 设置主机信息
        try {
            if (logger.getHostName() == null) {
                logger.setHostName(InetAddress.getLocalHost().getHostName());
            }
            if (logger.getHostIp() == null) {
                logger.setHostIp(InetAddress.getLocalHost().getHostAddress());
            }
        } catch (Exception e) {
            log.warn("获取主机信息失败: {}", e.getMessage());
        }

        // 处理SQL参数
        if (logger.getSqlParams() != null && !logger.getSqlParams().isEmpty()) {
            try {
                // 如果参数不是JSON格式，尝试转换为JSON
                if (!logger.getSqlParams().startsWith("{")) {
                    logger.setSqlParams(objectMapper.writeValueAsString(logger.getSqlParams()));
                }
            } catch (JsonProcessingException e) {
                log.warn("SQL参数JSON转换失败: {}", e.getMessage());
            }
        }

        // 截断过长的字段
        if (StringUtils.hasText(logger.getSqlText()) && logger.getSqlText().length() > 4000) {
            logger.setSqlText(logger.getSqlText().substring(0, 4000) + "...");
        }

        if (StringUtils.hasText(logger.getErrorMessage()) && logger.getErrorMessage().length() > 2000) {
            logger.setErrorMessage(logger.getErrorMessage().substring(0, 2000) + "...");
        }
    }

    /**
     * 获取当前用户ID（可以从SecurityContext或ThreadLocal中获取）
     */
    private String getCurrentUserId() {
        // TODO: 实现从SecurityContext获取当前用户ID的逻辑
        return "system";
    }

    /**
     * 获取当前用户IP地址
     */
    private String getCurrentUserIp() {
        // TODO: 实现从HttpServletRequest获取用户IP的逻辑
        return "127.0.0.1";
    }

    /**
     * 判断SQL类型
     */
    private String getQueryType(String sql) {
        if (sql == null) {
            return "UNKNOWN";
        }

        String upperSql = sql.trim().toUpperCase();
        if (upperSql.startsWith("SELECT")) {
            return "SELECT";
        } else if (upperSql.startsWith("INSERT")) {
            return "INSERT";
        } else if (upperSql.startsWith("UPDATE")) {
            return "UPDATE";
        } else if (upperSql.startsWith("DELETE")) {
            return "DELETE";
        } else {
            return "OTHER";
        }
    }

    /**
     * 应用关闭时清理资源
     */
    public void shutdown() {
        // 清理批量处理队列
        if (batchQueue != null) {
            batchQueue.clear();
        }
        log.info("SQL监控服务已关闭");
    }
}
